package toledo.rest;

import java.util.List;
import java.util.Vector;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;

@Path("/user")
public class User
{
	public static final String DATABASE = "users";
	public static final String TWITTER_ID = "twitter_id";
	public static final String USER_ID = "user_id";
	public static final String USERNAME = "username";
	public static final String PASSWORD = "password";
	public static final String KEY = Entity.KEY_RESERVED_PROPERTY;
	public static final String LAST_UPDATE_ID = "last_update_id";
	public static final String PIC_URL = "pic_url";
	public static final String FULLNAME = "fullname";
	
	public static Entity getUser(Object user_id)
	{
		try
		{
			return DatastoreServiceFactory.getDatastoreService().get(KeyFactory.stringToKey(user_id.toString()));
		}
		catch(EntityNotFoundException e)
		{
			
		}
		return null;
	}
	@Path("/valid_login")
	@GET
	@Produces("application/json")
	public String isValidLogin(@QueryParam(User.USERNAME)String username,@QueryParam(User.PASSWORD)String password)
	{
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		JSONObject json = new JSONObject();
		
		List<Entity> users = ds.prepare(new Query(User.DATABASE).addFilter(User.USERNAME,FilterOperator.EQUAL,username).addFilter(User.PASSWORD,FilterOperator.EQUAL,password)).asList(FetchOptions.Builder.withDefaults());
		
		try
		{
			json.put("logged_in",users.size());
			if(users.size()>0)
				json.put(User.USER_ID,KeyFactory.keyToString(users.get(0).getKey()));
		}
		catch (JSONException e)
		{
		}
		
		return json.toString();
	}
	@Path("/courses")
	@GET
	@Produces("application/json")
	public String getCourses(@QueryParam(User.USER_ID)String user_id)
	{
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		JSONObject json = new JSONObject();
		Vector<JSONObject> list = new Vector<JSONObject>();
		
		List<Entity> user_to_courses = ds.prepare(new Query(UserToCourse.DATABASE).addFilter(User.USER_ID,FilterOperator.EQUAL,user_id)).asList(FetchOptions.Builder.withDefaults());
		for(Entity user_to_course:user_to_courses)
		{
			try
			{
				Entity course = Course.getCourse(user_to_course.getProperty(UserToCourse.COURSE_ID));
				JSONObject o = new JSONObject();
				o.put(Course.COURSE_ID,KeyFactory.keyToString(course.getKey()));
				o.put(Course.COURSENAME,course.getProperty(Course.COURSENAME));
				o.put(Course.HASHTAG,course.getProperty(Course.HASHTAG));
				list.add(o);
			}
			catch(JSONException e)
			{
			}
		}
		
		JSONArray results = new JSONArray(list);
		try
		{
			json.put("results",results);
		}
		catch (JSONException e)
		{
		}
		
		return json.toString();
	}
	@Path("/updates")
	@GET
	@Produces("application/json")
	public String getUpdates(@QueryParam(User.USER_ID)String user_id,@QueryParam(User.LAST_UPDATE_ID)String last_update_id)
	{
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		JSONObject json = new JSONObject();
		Vector<JSONObject> list = new Vector<JSONObject>();
		
		String new_last_update_id = "";
		
		List<Entity> user_to_courses = ds.prepare(new Query(UserToCourse.DATABASE).addFilter(User.USER_ID,FilterOperator.EQUAL,user_id)).asList(FetchOptions.Builder.withDefaults());
		for(Entity user_to_course:user_to_courses)
		{
			try
			{
				Query query = new Query(Update.DATABASE).addFilter(Course.COURSE_ID,FilterOperator.EQUAL,user_to_course.getProperty(UserToCourse.COURSE_ID)).addFilter(User.USER_ID,FilterOperator.NOT_EQUAL,user_id);
				if(last_update_id!=null&&!last_update_id.equals(""))
					query = query.addFilter(Update.KEY,FilterOperator.GREATER_THAN,last_update_id);
				List<Entity> updates = ds.prepare(query).asList(FetchOptions.Builder.withDefaults()); //contains entry id
				
				for(Entity update:updates)
				{
					Entity entry = Entry.getEntry(update.getProperty(Update.ENTRY_ID));
					Entity user = User.getUser(entry.getProperty(Entry.USER_ID));
					Entity course = Course.getCourse(entry.getProperty(Entry.COURSE_ID));
					
					JSONObject o = new JSONObject();
					o.put(Update.COURSE_ID,entry.getProperty(Entry.COURSE_ID));
					o.put(Update.ENTRY_ID,update.getProperty(Update.ENTRY_ID));
					o.put(Update.TYPE,entry.getProperty(Entry.TYPE));
					o.put(Update.TEXT,entry.getProperty(Entry.TEXT));
					o.put(Update.REPLY_TO_ID,entry.getProperty(Entry.REPLY_TO_ID));
					o.put(Update.FULLNAME,user.getProperty(User.FULLNAME));
					o.put(Update.PIC_URL,user.getProperty(User.PIC_URL));
					o.put(Update.DATE,entry.getProperty(Entry.DATE));
					o.put(Update.COURSENAME,course.getProperty(Course.COURSENAME));
					
					String key = KeyFactory.keyToString(update.getKey());
					if(key.compareTo(new_last_update_id)>0)
						new_last_update_id = key;
					
					list.add(o);
				}
			}
			catch(JSONException e)
			{
			}
		}
		/*"date":"DATE",
		  "course_name":"COURSE_NAME" */
		
		JSONArray results = new JSONArray(list);
		try
		{
			json.put("last_update_id",new_last_update_id);
			json.put("results",results);
		}
		catch (JSONException e)
		{
		}
		
		return json.toString();
	}
}
